#ifndef GTD_PROFILER_HPP
#define GTD_PROFILER_HPP
#include "gtd_common.hpp"

NAMESPACE_BEG(gtd)

#if GTD_PROFILING

class Profiler
{
public:
    struct Record;

    class Sample
    {
    public:
        Sample(const char* name);
        ~Sample();

    private:
        Record* record;
    };

    static void print(std::ostream&);
    static void reset();

private:
    static std::map<std::string, Record*> records;
    static Record* current;
    static std::vector<Record*> roots;
};

#define PROFILE(name) gtd::Profiler::Sample CONCAT(sample, __LINE__)(name)
#define PROFILER_PRINT(stream) gtd::Profiler::print(stream)
#define PROFILER_RESET() gtd::Profiler::reset()
#define PROFILER_CUDA_BARRIER() CUDA_ERROR_CHECK(cudaThreadSynchronize())

#else

#define PROFILE(name)
#define PROFILER_PRINT(stream)
#define PROFILER_RESET()
#define PROFILER_CUDA_BARRIER()

#endif

NAMESPACE_END(gtd)

#endif
